package com.sciencep.pro.core.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sciencep.pro.common.config.Constant;
import com.sciencep.pro.common.domain.QueryRequest;
import com.sciencep.pro.common.domain.ResponseResult;
import com.sciencep.pro.common.exception.CustomException;
import com.sciencep.pro.common.utils.SortUtil;
import com.sciencep.pro.core.dao.UserWorkdailyLogMapper;
import com.sciencep.pro.core.domain.dto.dropdown.ProSelectVO;
import com.sciencep.pro.core.domain.dto.user.UserDetail;
import com.sciencep.pro.core.domain.dto.workdailylog.*;
import com.sciencep.pro.core.domain.entity.*;
import com.sciencep.pro.core.domain.vo.workdailylog.WorkDailyLogVo;
import com.sciencep.pro.core.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;


/**
 * @author Sciencep
 */
@Service
@Slf4j
public class UserWorkdailyLogServiceImpl extends ServiceImpl<UserWorkdailyLogMapper, UserWorkdailyLog> implements IUserWorkdailyLogService {

    @Resource
    private UserWorkdailyLogMapper userWorkdailyLogMapper;

    @Autowired
    IDeptService deptService;

    @Autowired
    IUserDeptService userDeptService;

    @Resource
    IProBaseInfoService proBaseInfoService;

    @Autowired
    IProPlanHoursService proPlanHoursService;

    @Autowired
    IProNodeService nodeService;

    @Autowired
    IUserWorkdailyLogBackService userWorkdailyLogBackService;

    @Autowired
    IUserAttendanceBackService userAttendanceBackService;

    @Autowired
    IUserService userService;

    @Autowired
    IProAssignmentService proAssignmentService;

    String yMd = "yyyy-MM-dd";

    String yMdHms = "yyyy-MM-dd HH:mm:ss";

    String yMdHm = "yyyy-MM-dd HH:mm";

    Pattern pattern = Pattern.compile("[0-9]*");

    @Override
    public List<WorkDailyListResponseTO> getLogList(String userId, String date) throws CustomException {

        // 根据工作日期聚类
        List<WorkDailyListResponseTO> result = baseMapper.getLogList(date, userId);
        DateFormat formatter = new SimpleDateFormat(yMd);

        // 将日期拆成年月日
        if (CollUtil.isNotEmpty(result)) {
            result.forEach(o -> {
                try {
                    String workDate = o.getWorkDate();
                    formatter.parse(workDate);
                    String[] dateList = workDate.split("-");
                    o.setYear(dateList[0]);
                    o.setMonth(dateList[1]);
                    o.setDay(dateList[2]);
                } catch (Exception e) {
                    log.error(e.getMessage());
                }
            });
        }
        return result;
    }

    @Override
    public List<WorkLogDetailTO> getMyLog(String userId, String beginMonth, String endMonth) {

        LocalDate startDate = StringUtils.isEmpty(beginMonth) ? null :
                LocalDate.parse(beginMonth + "-01", DateTimeFormatter.ofPattern(yMd));
        LocalDate endDate = StringUtils.isEmpty(endMonth) ? null :
                LocalDate.parse(endMonth + "-01", DateTimeFormatter.ofPattern(yMd)).plusMonths(1);

        return baseMapper.getMyLog(startDate, endDate, userId);
    }

    @Override
    public List<UserWorkdailyLog> getDetail(String userId, String date, String proNo) {

        List<UserWorkdailyLog> result = this.list(new LambdaQueryWrapper<UserWorkdailyLog>().eq(UserWorkdailyLog::getUserId, userId)
                .like(UserWorkdailyLog::getWorkDate, date).orderByAsc(UserWorkdailyLog::getId));
        DateFormat formatter = new SimpleDateFormat(yMd);
        for (UserWorkdailyLog o : result) {
            try {
                String workDate = formatter.format(o.getWorkDate());
                String[] dateList = workDate.split("-");
                o.setYear(dateList[0]);
                o.setMonth(dateList[1]);
                o.setDay(dateList[2]);
            } catch (Exception e) {
                log.error(e.getMessage());
            }
        }
        List<ProNode> proNodeList = nodeService.list();
        if (CollUtil.isNotEmpty(result) && CollUtil.isNotEmpty(proNodeList)) {
            for (UserWorkdailyLog userWorkdailyLog : result) {
                for (ProNode proNode : proNodeList) {
                    if (userWorkdailyLog.getNodeId() != null && userWorkdailyLog.getNodeId().equals(proNode.getId())) {
                        userWorkdailyLog.setNodeName(proNode.getNodeName());
                    }
                }
            }
        }
        return result;
    }

    @Override
    public Page<WorkdailyLogTO> getWorkDailyReviewList(QueryRequest queryRequest, WorkDailyLogVo workDailyLogVo) {
        Page<WorkdailyLogTO> page = new Page<>();
        SortUtil.handlePageSort(queryRequest, page);
        return userWorkdailyLogMapper.getWorkDailyReviewList(page, workDailyLogVo);
    }

    @Override
    public Page<WorkdailyLogTO> getWorkDailyReviewListBack(QueryRequest queryRequest, WorkDailyLogVo workDailyLogVo) {
        Page<WorkdailyLogTO> page = new Page<>();
        SortUtil.handlePageSort(queryRequest, page);
        return userWorkdailyLogMapper.getWorkDailyReviewListBack(page, workDailyLogVo);
    }

    @Override
    public List<WorkdailyLogTO> getWorkDailyReviewListExport(WorkDailyLogVo workDailyLogVo) {
        return userWorkdailyLogMapper.getWorkDailyReviewListExport(workDailyLogVo);
    }

    @Override
    public List<WorkdailyLogTO> exportWorkDailyReviewDetail(WorkDailyLogVo workDailyLogVo) {
        return userWorkdailyLogMapper.exportWorkDailyReviewDetail(workDailyLogVo);
    }

    @Override
    public Page<WorkLogDetailTO> getWorkLogDetailTOPage(QueryRequest queryRequest, WorkDailyLogRequestTO requestTO) {

        //得到可以看的项目范围
        List<ProSelectVO> proSelectVOS = proBaseInfoService.getInprocessingProList(requestTO.getMangerId());
        Set<String> proNos = proSelectVOS.stream().map(ProSelectVO::getProNo).collect(Collectors.toSet());
        //得到用户是项目经理的所在部门列表
        Set<String> deptSet = deptService.
                list(new LambdaQueryWrapper<Dept>().like(Dept::getDeptManagerUseridList, requestTO.getMangerId()))
                .stream().map(Dept::getDeptId).collect(Collectors.toSet());
        //得到用户是项目经理的所在部门列表和其子部门
        if (CollUtil.isNotEmpty(deptSet)) {
            List<Dept> depts = deptService.list();
            deptSet = ProBaseInfoServiceImpl.getSubDeptList(deptSet, depts);
        }
        Page<WorkLogDetailTO> page = new Page<>();
        page.setSize(queryRequest.getPageSize());
        page.setCurrent(queryRequest.getPageNum());
        //去除掉其它项目
        proNos.remove("OTHER0001");
        // 查询逻辑 :   项目经理的部门和子部门的员工的其它项目的日志  或者 指定项目了话 查看指定项目  没有指定项目了话 显示可见项目范围的日志
        Page<WorkLogDetailTO> result = new Page<>();
        if (CollUtil.isNotEmpty(proNos) || CollUtil.isNotEmpty(deptSet)) {
            result = baseMapper.getWorkLogDetailTOPage(page, requestTO.getReviewStatus(),
                    requestTO.getBeginDate(), requestTO.getEndDate(), null, requestTO.getProNo(), requestTO.getMangerId(), proNos, deptSet);
        }

        return result;
    }

    @Override
    public Page<WorkLogDetailTO> getWorkLogDetailTOPageNew(QueryRequest queryRequest, WorkDailyLogRequestTO requestTO) {

        //得到可以看的项目范围
        //List<ProSelectVO> proSelectVOS = proBaseInfoService.getInprocessingProList(requestTO.getMangerId());

        List<ProSelectVO> proSelectVOS = new ArrayList<>();
        //人天分配表中指定的日志评审人
        List<ProAssignment> proAssignmentList = proAssignmentService.list(new LambdaQueryWrapper<ProAssignment>().
                groupBy(ProAssignment::getProId,ProAssignment::getUserId).
                eq(ProAssignment::getReviewId, requestTO.getMangerId()));
        Set<Long> proAssignmentNo = proAssignmentList.stream().map(ProAssignment::getProId).collect(Collectors.toSet());
        Set<String> proUserIdSet = proAssignmentList.stream().map(ProAssignment::getUserId).collect(Collectors.toSet());
        List<ProSelectVO> proAssignmentNos = new ArrayList<>();
        proAssignmentNo.forEach(e->{
            ProSelectVO proSelectVO = new ProSelectVO();
            proSelectVO.setProNo(proBaseInfoService.getOne(new LambdaQueryWrapper<ProBaseInfo>().eq(ProBaseInfo::getId,e)).getProCode());
            proSelectVO.setProName(proBaseInfoService.getOne(new LambdaQueryWrapper<ProBaseInfo>().eq(ProBaseInfo::getId,e)).getProName());
            proAssignmentNos.add(proSelectVO);
        });
        proSelectVOS.addAll(proAssignmentNos);

        Set<String> proNos = proSelectVOS.stream().map(ProSelectVO::getProNo).collect(Collectors.toSet());
        Page<WorkLogDetailTO> page = new Page<>();
        page.setSize(queryRequest.getPageSize());
        page.setCurrent(queryRequest.getPageNum());
        //得到用户是项目主管的所在部门列表
        Set<String> deptSet = deptService.
                list(new LambdaQueryWrapper<Dept>().like(Dept::getDeptManagerUseridList, requestTO.getMangerId()))
                .stream().map(Dept::getDeptId).collect(Collectors.toSet());
        //递归查询部门下所有部门
        Set<String> allFollowDeptSet = new HashSet<>();
        if(!CollectionUtils.isEmpty(deptSet)){
            allFollowDeptSet.addAll(deptSet);
            for(String tempDept : deptSet){
                queryfollowdeptSet(allFollowDeptSet,tempDept);
            }
        }

        //找到项目主管下的所有人
        Set<String> userSet = new HashSet<>();
        allFollowDeptSet.forEach(e -> {
            userDeptService.list(new LambdaQueryWrapper<UserDept>().eq(UserDept::getDeptId,e)).forEach(d->{
                userSet.add(d.getUserId());
            });
        });

        //去除掉其它项目
        proNos.remove("OTHER0001");
        // 查询逻辑 :   项目主管的部门员工的日志和其它项目的日志  或者 指定项目的日志评审人
        Page<WorkLogDetailTO> result = new Page<>();
        if(CollUtil.isNotEmpty(allFollowDeptSet) || CollUtil.isNotEmpty(userSet) || CollUtil.isNotEmpty(proNos)) {
            result = baseMapper.getWorkLogDetailTOPageNew(page, requestTO.getReviewStatus(),
                    requestTO.getBeginDate(), requestTO.getEndDate(), null, requestTO.getProNo(), requestTO.getMangerId(), proUserIdSet, allFollowDeptSet, userSet,proNos);
        }
        return result;
    }

    private void queryfollowdeptSet(Set<String> deptSet, String tempDept) {
        Set<String> tempSet = deptService.list(new LambdaQueryWrapper<Dept>().like(Dept::getParentId, tempDept))
                .stream().map(Dept::getDeptId).collect(Collectors.toSet());
        if(!CollectionUtils.isEmpty(tempSet)){
            for(String temp : tempSet){
                deptSet.add(temp);
                queryfollowdeptSet(deptSet,temp);
            }
        }
        return;
    }


    @Override
    public void reviewWorkDailyLog(ReviewTO requestTO, UserDetail userDetail) throws CustomException {

        UserWorkdailyLog userWorkdailyLog = getById(requestTO.getLogId());
        if (null == userWorkdailyLog) {
                throw new CustomException("该日志不存在");
        }
        userWorkdailyLog.setPutinDaily(requestTO.getPutinDaily()).setPerformanceDaily(requestTO.getPerformanceDaily());
        userWorkdailyLog.setWorkDate(requestTO.getWorkDate());
        userWorkdailyLog.setUserDept(requestTO.getDeptId());
        userWorkdailyLog.setDeptName(requestTO.getDeptName());
        userWorkdailyLog.setDailyLog(requestTO.getDailyLog());
        userWorkdailyLog.setProNo(requestTO.getProNo());
        if (requestTO.getProNo().equals("OTHER0001")) {
            userWorkdailyLog.setProName("其他");
        } else {
            userWorkdailyLog.setProName(proBaseInfoService.getOne(new LambdaQueryWrapper<ProBaseInfo>().eq(ProBaseInfo::getProCode, requestTO.getProNo())).getProName());
        }
        userWorkdailyLog.setRemark(requestTO.getRemark());
        userWorkdailyLog.setTomorrowPlan(requestTO.getTomorrowPlan());
        userWorkdailyLog.setReviewStatus(Constant.ReviewStatus.YES + "").setReviewTime(new Date());
        userWorkdailyLog.setModifyDate(new Date());
        userWorkdailyLog.setReviewName(userDetail.getUserName());
        userWorkdailyLog.setDevPoint(requestTO.getDevPoint());
        userWorkdailyLog.setModifyUserId(userDetail.getUserId());
        userWorkdailyLog.setModifyUserName(userDetail.getUserName());

        UserWorkdailyLogBack userWorkdailyLogBack = new UserWorkdailyLogBack();
        userWorkdailyLogBack.setType("1");//系统内的人员
        BeanUtils.copyProperties(userWorkdailyLog, userWorkdailyLogBack);
        userWorkdailyLogBackService.save(userWorkdailyLogBack);

        this.updateById(userWorkdailyLog);
    }

    @Override
    public void reviewWorkDailyLogBatch(List<String> idList, UserDetail userDetail) {
        List<UserWorkdailyLog> logList = this.listByIds(idList);
        List<UserWorkdailyLogBack> logBackList = new ArrayList<>();
        for (UserWorkdailyLog userWorkdailyLog : logList) {
            userWorkdailyLog.setReviewTime(new Date()).setReviewStatus(Constant.ReviewStatus.YES + "");
            userWorkdailyLog.setModifyDate(new Date());
            userWorkdailyLog.setReviewName(userDetail.getUserName());
            userWorkdailyLog.setModifyUserId(userDetail.getUserId());
            userWorkdailyLog.setModifyUserName(userDetail.getUserName());
            UserWorkdailyLogBack userWorkdailyLogBack = new UserWorkdailyLogBack();
            userWorkdailyLogBack.setType("1");//系统内的人员
            BeanUtils.copyProperties(userWorkdailyLog, userWorkdailyLogBack);
            logBackList.add(userWorkdailyLogBack);
        }
        this.updateBatchById(logList);
        userWorkdailyLogBackService.saveBatch(logBackList);
    }

    @Override
    public int selectCount(UserWorkdailyLog userWorkdailyLog) {
        return baseMapper.selectCount(userWorkdailyLog);
    }

    @Override
    public int isReview(UserWorkdailyLog userWorkdailyLog) {
        return baseMapper.isReview(userWorkdailyLog);
    }

    @Override
    @Transactional
    public ResponseResult<UserWorkdailyLog> importWorkDailyReviewDetail(List<WorkdailyLogTO> list, UserDetail detail) throws ParseException {
        if (CollUtil.isNotEmpty(list)) {
            //校验
            if(Boolean.FALSE.equals(checkOut(list).getSuccess())){
                return checkOut(list);
            }

            List<UserWorkdailyLogBack> updateUserWorkdailyLogBackList = new ArrayList<>();
            List<UserAttendanceBack> updateUserAttendanceBackList = new ArrayList<>();
            List<UserWorkdailyLogBack> insertUserWorkdailyLogBackList = new ArrayList<>();
            List<UserAttendanceBack> insertUserAttendanceBackList = new ArrayList<>();
            for (WorkdailyLogTO workdailyLogTO : list) {
                UserWorkdailyLogBack userWorkdailyLogBack = new UserWorkdailyLogBack();
                UserAttendanceBack userAttendanceBack = new UserAttendanceBack();
                if (null != workdailyLogTO.getId() && !workdailyLogTO.getId().equals("")) {
                    //日志备份表操作
                    SimpleDateFormat sdfUserWorkdailyLog = new SimpleDateFormat(yMd);
                    if (CollUtil.isNotEmpty(userService.list(new LambdaQueryWrapper<User>().eq(User::getUserId, workdailyLogTO.getUserId())))) {
                        userWorkdailyLogBack.setType("1");
                    } else {
                        userWorkdailyLogBack.setType("0");
                    }
                    userWorkdailyLogBack.setId(Long.valueOf(workdailyLogTO.getId()));
                    userWorkdailyLogBack.setUserId(workdailyLogTO.getUserId());
                    userWorkdailyLogBack.setUserName(workdailyLogTO.getUserName());
                    userWorkdailyLogBack.setUserDept(workdailyLogTO.getDeptId());
                    userWorkdailyLogBack.setDeptName(workdailyLogTO.getDeptName());
                    userWorkdailyLogBack.setProNo(workdailyLogTO.getProNo());
                    userWorkdailyLogBack.setProName(workdailyLogTO.getProName());
                    if(isNumeric(workdailyLogTO.getWorkDate())){
                        userWorkdailyLogBack.setWorkDate(HSSFDateUtil.getJavaDate(Double.valueOf(workdailyLogTO.getWorkDate())));
                    }else{
                        userWorkdailyLogBack.setWorkDate(sdfUserWorkdailyLog.parse(workdailyLogTO.getWorkDate()));
                    }
                    userWorkdailyLogBack.setPerformanceDaily(workdailyLogTO.getPerformanceDaily());
                    userWorkdailyLogBack.setPutinDaily(workdailyLogTO.getPutinDaily());
                    userWorkdailyLogBack.setNodeName(workdailyLogTO.getNodeName());
                    userWorkdailyLogBack.setDevPoint(workdailyLogTO.getDevPoint());
                    userWorkdailyLogBack.setDailyLog(workdailyLogTO.getDailyLog());
                    userWorkdailyLogBack.setTomorrowPlan(workdailyLogTO.getTomorrowPlan());
                    userWorkdailyLogBack.setRemark(workdailyLogTO.getDailyRemark());
                    userWorkdailyLogBack.setModifyUserId(detail.getUserId());
                    userWorkdailyLogBack.setModifyUserName(detail.getUserName());
                    userWorkdailyLogBack.setModifyDate(new Date());
                    updateUserWorkdailyLogBackList.add(userWorkdailyLogBack);
                    //考勤表操作(考勤时间有才更新)
                    if (null != workdailyLogTO.getOnDutyTime() && !workdailyLogTO.getOnDutyTime().equals("") || null != workdailyLogTO.getOffDutyTime() && !workdailyLogTO.getOffDutyTime().equals("")) {
                        SimpleDateFormat sdf = new SimpleDateFormat(yMdHms);
                        SimpleDateFormat sdfhm = new SimpleDateFormat(yMdHm);
                        userAttendanceBack.setId(Long.valueOf(workdailyLogTO.getAttendanceId()));
                        userAttendanceBack.setUserId(workdailyLogTO.getUserId());
                        userAttendanceBack.setUserName(workdailyLogTO.getUserName());
                        if(isNumeric(workdailyLogTO.getWorkDate())){
                            userAttendanceBack.setDutyDate(HSSFDateUtil.getJavaDate(Double.valueOf(workdailyLogTO.getWorkDate())));
                        }else{
                            userAttendanceBack.setDutyDate(sdfUserWorkdailyLog.parse(workdailyLogTO.getWorkDate()));
                        }
                        if (null != workdailyLogTO.getOnDutyTime() && !workdailyLogTO.getOnDutyTime().equals("")) {
                            if(this.isDate(workdailyLogTO.getOnDutyTime(), yMdHms)){
                                userAttendanceBack.setOnDutyTime(sdf.parse(workdailyLogTO.getOnDutyTime()));
                            }else if(this.isDate(workdailyLogTO.getOnDutyTime(), yMdHm)){
                                userAttendanceBack.setOnDutyTime(sdfhm.parse(workdailyLogTO.getOnDutyTime()));
                            }else{
                                userAttendanceBack.setOnDutyTime(HSSFDateUtil.getJavaDate(Double.valueOf(workdailyLogTO.getOnDutyTime())));
                            }
                        }
                        if (null != workdailyLogTO.getOffDutyTime() && !workdailyLogTO.getOffDutyTime().equals("")) {
                            if(this.isDate(workdailyLogTO.getOffDutyTime(), yMdHms)){
                                userAttendanceBack.setOffDutyTime(sdf.parse(workdailyLogTO.getOffDutyTime()));
                            }else if(this.isDate(workdailyLogTO.getOffDutyTime(), yMdHm)){
                                userAttendanceBack.setOffDutyTime(sdfhm.parse(workdailyLogTO.getOffDutyTime()));
                            }else{
                                userAttendanceBack.setOffDutyTime(HSSFDateUtil.getJavaDate(Double.valueOf(workdailyLogTO.getOffDutyTime())));
                            }
                        }
                        updateUserAttendanceBackList.add(userAttendanceBack);
                    }
                } else {
                    //日志备份表操作(项目编号存在就保存)
                    if (null != workdailyLogTO.getProNo() && !workdailyLogTO.getProNo().equals("")) {
                        SimpleDateFormat sdfUserWorkdailyLog = new SimpleDateFormat(yMd);
                        if (CollUtil.isNotEmpty(userService.list(new LambdaQueryWrapper<User>().eq(User::getUserId, workdailyLogTO.getUserId())))) {
                            userWorkdailyLogBack.setType("1");
                        } else {
                            userWorkdailyLogBack.setType("0");
                        }
                        userWorkdailyLogBack.setUserId(workdailyLogTO.getUserId());
                        userWorkdailyLogBack.setUserName(workdailyLogTO.getUserName());
                        userWorkdailyLogBack.setUserDept(workdailyLogTO.getDeptId());
                        userWorkdailyLogBack.setDeptName(workdailyLogTO.getDeptName());
                        userWorkdailyLogBack.setProNo(workdailyLogTO.getProNo());
                        userWorkdailyLogBack.setProName(workdailyLogTO.getProName());
                        if(isNumeric(workdailyLogTO.getWorkDate())){
                            userWorkdailyLogBack.setWorkDate(HSSFDateUtil.getJavaDate(Double.valueOf(workdailyLogTO.getWorkDate())));
                        }else{
                            userWorkdailyLogBack.setWorkDate(sdfUserWorkdailyLog.parse(workdailyLogTO.getWorkDate()));
                        }
                        userWorkdailyLogBack.setPerformanceDaily(workdailyLogTO.getPerformanceDaily());
                        userWorkdailyLogBack.setPutinDaily(workdailyLogTO.getPutinDaily());
                        userWorkdailyLogBack.setNodeName(workdailyLogTO.getNodeName());
                        userWorkdailyLogBack.setDevPoint(workdailyLogTO.getDevPoint());
                        userWorkdailyLogBack.setDailyLog(workdailyLogTO.getDailyLog());
                        userWorkdailyLogBack.setTomorrowPlan(workdailyLogTO.getTomorrowPlan());
                        userWorkdailyLogBack.setRemark(workdailyLogTO.getDailyRemark());
                        userWorkdailyLogBack.setModifyUserId(detail.getUserId());
                        userWorkdailyLogBack.setModifyUserName(detail.getUserName());
                        userWorkdailyLogBack.setModifyDate(new Date());

                        insertUserWorkdailyLogBackList.add(userWorkdailyLogBack);
                        //考勤表操作(考勤时间有才更新)
                        if (null != workdailyLogTO.getOnDutyTime() && !workdailyLogTO.getOnDutyTime().equals("") || null != workdailyLogTO.getOffDutyTime() && !workdailyLogTO.getOffDutyTime().equals("")) {
                            SimpleDateFormat sdf = new SimpleDateFormat(yMdHms);
                            SimpleDateFormat sdfhm = new SimpleDateFormat(yMdHm);
                            userAttendanceBack.setUserId(workdailyLogTO.getUserId());
                            userAttendanceBack.setUserName(workdailyLogTO.getUserName());
                            if(isNumeric(workdailyLogTO.getWorkDate())){
                                userAttendanceBack.setDutyDate(HSSFDateUtil.getJavaDate(Double.valueOf(workdailyLogTO.getWorkDate())));
                            }else{
                                userAttendanceBack.setDutyDate(sdfUserWorkdailyLog.parse(workdailyLogTO.getWorkDate()));
                            }
                            if (null != workdailyLogTO.getOnDutyTime() && !workdailyLogTO.getOnDutyTime().equals("")) {
                                if(this.isDate(workdailyLogTO.getOnDutyTime(), yMdHms)){
                                    userAttendanceBack.setOnDutyTime(sdf.parse(workdailyLogTO.getOnDutyTime()));
                                }else if(this.isDate(workdailyLogTO.getOnDutyTime(), yMdHm)){
                                    userAttendanceBack.setOnDutyTime(sdfhm.parse(workdailyLogTO.getOnDutyTime()));
                                }else{
                                    userAttendanceBack.setOnDutyTime(HSSFDateUtil.getJavaDate(Double.valueOf(workdailyLogTO.getOnDutyTime())));
                                }
                            }
                            if (null != workdailyLogTO.getOffDutyTime() && !workdailyLogTO.getOffDutyTime().equals("")) {
                                if(this.isDate(workdailyLogTO.getOffDutyTime(), yMdHms)){
                                    userAttendanceBack.setOffDutyTime(sdf.parse(workdailyLogTO.getOffDutyTime()));
                                }else if(this.isDate(workdailyLogTO.getOffDutyTime(), yMdHm)){
                                    userAttendanceBack.setOffDutyTime(sdfhm.parse(workdailyLogTO.getOffDutyTime()));
                                }else{
                                    userAttendanceBack.setOffDutyTime(HSSFDateUtil.getJavaDate(Double.valueOf(workdailyLogTO.getOffDutyTime())));
                                }
                            }
                            //数据库中没有就保存到数组
                            if(CollUtil.isEmpty(
                            userAttendanceBackService.list(new LambdaQueryWrapper<UserAttendanceBack>().
                                    eq(UserAttendanceBack::getUserName,userAttendanceBack.getUserName()).
                                    eq(null != workdailyLogTO.getOnDutyTime(),UserAttendanceBack::getOnDutyTime,workdailyLogTO.getOnDutyTime()).
                                    eq(null != workdailyLogTO.getOffDutyTime(),UserAttendanceBack::getOffDutyTime,workdailyLogTO.getOffDutyTime()).
                                    eq(UserAttendanceBack::getDutyDate,workdailyLogTO.getWorkDate())) )){
                                insertUserAttendanceBackList.add(userAttendanceBack);
                            }
                        }
                    }
                }
            }
            if (CollUtil.isNotEmpty(updateUserWorkdailyLogBackList)) {
                userWorkdailyLogBackService.updateBatchById(updateUserWorkdailyLogBackList);
            }
            if (CollUtil.isNotEmpty(updateUserAttendanceBackList)) {
                userAttendanceBackService.updateBatchById(updateUserAttendanceBackList);
            }
            if (CollUtil.isNotEmpty(insertUserWorkdailyLogBackList)) {
                //去重
                userWorkdailyLogBackService.saveBatch(insertUserWorkdailyLogBackList.stream().distinct().collect(Collectors.toList()));
            }
            if (CollUtil.isNotEmpty(insertUserAttendanceBackList)) {
                //去重
                userAttendanceBackService.saveBatch(insertUserAttendanceBackList.stream().distinct().collect(Collectors.toList()));
            }
            return new ResponseResult<UserWorkdailyLog>().success();
        }
        return new ResponseResult<UserWorkdailyLog>().failure();
    }

    private ResponseResult<UserWorkdailyLog> checkOut(List<WorkdailyLogTO> list) {
        //校验
        int rowNum = 1;
        for (WorkdailyLogTO workdailyLogTO : list) {
            rowNum++;

            //用户名称不能为空
            if (null == workdailyLogTO.getUserName()) {
                return new ResponseResult<UserWorkdailyLog>().failure("1001", "第" + rowNum + "行,用户名称:不能为空");
            }
            //部门名称不能为空
            if (null == workdailyLogTO.getDeptName()) {
                return new ResponseResult<UserWorkdailyLog>().failure("1001", "第" + rowNum + "行,部门名称:不能为空");
            }
            //项目编号不能为空
            if (null == workdailyLogTO.getProNo()) {
                return new ResponseResult<UserWorkdailyLog>().failure("1001", "第" + rowNum + "行,项目编号:不能为空");
            }
            //项目名称不能为空
            if (null == workdailyLogTO.getProName()) {
                return new ResponseResult<UserWorkdailyLog>().failure("1001", "第" + rowNum + "行,项目名称:不能为空");
            }
            //打卡日期不能为空
            if (null == workdailyLogTO.getWorkDate()) {
                return new ResponseResult<UserWorkdailyLog>().failure("1001", "第" + rowNum + "行,打卡日期:不能为空");
            }
            //投入人天不能为空
            if (null == workdailyLogTO.getPutinDaily()) {
                return new ResponseResult<UserWorkdailyLog>().failure("1001", "第" + rowNum + "行,投入人天:不能为空");
            }
            //绩效人天不能为空
            if (null == workdailyLogTO.getPerformanceDaily()) {
                return new ResponseResult<UserWorkdailyLog>().failure("1001", "第" + rowNum + "行,绩效人天:不能为空");
            }
            //项目节点不能为空
            if (null == workdailyLogTO.getNodeName()) {
                workdailyLogTO.setNodeName("无");
                //return new ResponseResult<UserWorkdailyLog>().failure("1001", "第" + rowNum + "行,项目节点:不能为空");
            }
            //开发节点不能为空
            if (null == workdailyLogTO.getDevPoint()) {
                workdailyLogTO.setDevPoint("无");
                //return new ResponseResult<UserWorkdailyLog>().failure("1001", "第" + rowNum + "行,开发节点:不能为空");
            }
            //今日工作不能为空
            if (null == workdailyLogTO.getDailyLog()) {
                workdailyLogTO.setDailyLog("无");
                //return new ResponseResult<UserWorkdailyLog>().failure("1001", "第" + rowNum + "行,今日工作:不能为空");
            }
            //明日工作不能为空
            if (null == workdailyLogTO.getTomorrowPlan()) {
                workdailyLogTO.setTomorrowPlan("无");
                //return new ResponseResult<UserWorkdailyLog>().failure("1001", "第" + rowNum + "行,明日工作:不能为空");
            }

            //长度校验(可为空)
            if (null != workdailyLogTO.getUserId() && workdailyLogTO.getUserId().length() > 64) {
                return new ResponseResult<UserWorkdailyLog>().failure("1001", "第" + rowNum + "行,用户ID:超出最大长度");
            }
            if (null != workdailyLogTO.getUserName() && workdailyLogTO.getUserName().length() > 64) {
                return new ResponseResult<UserWorkdailyLog>().failure("1001", "第" + rowNum + "行,用户名称:超出最大长度");
            }
            if (null != workdailyLogTO.getDeptId() && workdailyLogTO.getDeptId().length() > 64) {
                return new ResponseResult<UserWorkdailyLog>().failure("1001", "第" + rowNum + "行,部门ID:超出最大长度");
            }
            if (null != workdailyLogTO.getDeptName() && workdailyLogTO.getDeptName().length() > 64) {
                return new ResponseResult<UserWorkdailyLog>().failure("1001", "第" + rowNum + "行,部门名称:超出最大长度");
            }
            if (null != workdailyLogTO.getProNo() && workdailyLogTO.getProNo().length() > 50) {
                return new ResponseResult<UserWorkdailyLog>().failure("1001", "第" + rowNum + "行,项目编号:超出最大长度");
            }
            if (null != workdailyLogTO.getProName() && workdailyLogTO.getProName().length() > 200) {
                return new ResponseResult<UserWorkdailyLog>().failure("1001", "第" + rowNum + "行,项目名称:超出最大长度");
            }
            if (null != workdailyLogTO.getNodeName() && workdailyLogTO.getNodeName().length() > 50) {
                return new ResponseResult<UserWorkdailyLog>().failure("1001", "第" + rowNum + "行,项目节点:超出最大长度");
            }
            if (null != workdailyLogTO.getDevPoint() && workdailyLogTO.getDevPoint().length() > 50) {
                return new ResponseResult<UserWorkdailyLog>().failure("1001", "第" + rowNum + "行,开发节点:超出最大长度");
            }
            if (null != workdailyLogTO.getDailyLog() && workdailyLogTO.getDailyLog().length() > 1000) {
                return new ResponseResult<UserWorkdailyLog>().failure("1001", "第" + rowNum + "行,今日工作:超出最大长度");
            }
            if (null != workdailyLogTO.getTomorrowPlan() && workdailyLogTO.getTomorrowPlan().length() > 1000) {
                return new ResponseResult<UserWorkdailyLog>().failure("1001", "第" + rowNum + "行,明日工作:超出最大长度");
            }
            if (null != workdailyLogTO.getDailyRemark() && workdailyLogTO.getDailyRemark().length() > 1000) {
                return new ResponseResult<UserWorkdailyLog>().failure("1001", "第" + rowNum + "行,备注:超出最大长度");
            }

            //规则校验(可为空)
            if (null != workdailyLogTO.getDeptId() && !this.isNumeric(workdailyLogTO.getDeptId())) {
                return new ResponseResult<UserWorkdailyLog>().failure("1001", "第" + rowNum + "行,部门ID:必须是数字");
            }

            if (null != workdailyLogTO.getWorkDate() && !this.isDate(workdailyLogTO.getWorkDate(), yMd) && !isNumeric(workdailyLogTO.getWorkDate())) {
                return new ResponseResult<UserWorkdailyLog>().failure("1001", "第" + rowNum + "行,打卡日期:格式必须是yyyy-MM-dd或yyyy/MM/dd");
            }

            if (null != workdailyLogTO.getPutinDaily() && !isBigDecimal(workdailyLogTO.getPutinDaily().toString())) {
                return new ResponseResult<UserWorkdailyLog>().failure("1001", "第" + rowNum + "行,投入人天:必须是数字");
            }

            if (null != workdailyLogTO.getPerformanceDaily() && !isBigDecimal(workdailyLogTO.getPerformanceDaily().toString())) {
                return new ResponseResult<UserWorkdailyLog>().failure("1001", "第" + rowNum + "行,绩效人天:必须是数字");
            }

            if (null != workdailyLogTO.getOnDutyTime() && !this.isDate(workdailyLogTO.getOnDutyTime(), yMdHms) && !this.isDate(workdailyLogTO.getOnDutyTime(), yMdHm) && !isDouble(workdailyLogTO.getOnDutyTime())) {
                return new ResponseResult<UserWorkdailyLog>().failure("1001", "第" + rowNum + "行,上班打卡时间:格式必须是yyyy-MM-dd HH:mm:ss或yyyy-MM-dd HH:mm或yyyy/MM/dd HH:mm:ss或yyyy/MM/dd HH:mm");
            }

            if (null != workdailyLogTO.getOffDutyTime() && !this.isDate(workdailyLogTO.getOffDutyTime(), yMdHms) && !this.isDate(workdailyLogTO.getOffDutyTime(), yMdHm) && !isDouble(workdailyLogTO.getOffDutyTime())) {
                return new ResponseResult<UserWorkdailyLog>().failure("1001", "第" + rowNum + "行,下班打卡时间:格式必须是yyyy-MM-dd HH:mm:ss或yyyy-MM-dd HH:mm或yyyy/MM/dd HH:mm:ss或yyyy/MM/dd HH:mm");
            }

        }
        return new ResponseResult<UserWorkdailyLog>().success();
    }



    /**
     * 说明：判断是否为String
     *
     * @param str
     * @return
     */
    private boolean isNumeric(String str) {
        Matcher isNum = pattern.matcher(str);
        return isNum.matches();
    }

    public static boolean isDouble(String str){
        try {
            Double.parseDouble(str);
            return true;
        }catch(NumberFormatException ex){
            return false;
        }
    }

    /**
     * 说明：判断日期格式
     *
     * @param dttm,format
     * @return
     */
    private boolean isDate(String dttm, String format) {
        if (dttm == null) {
            return true;
        }
        if ( dttm.isEmpty() || format == null || format.isEmpty()) {
            return false;
        }
        if (format.replaceAll("'.+?'", "").indexOf("y") < 0) {
            format += "/yyyy";
            DateFormat formatter = new SimpleDateFormat("/yyyy");
            dttm += formatter.format(new Date());
        }
        DateFormat formatter = new SimpleDateFormat(format);
        formatter.setLenient(false);
        ParsePosition pos = new ParsePosition(0);
        Date date = formatter.parse(dttm, pos);
        if (date == null || pos.getErrorIndex() > 0) {
            return false;
        }
        if (pos.getIndex() != dttm.length()) {
            return false;
        }

        return formatter.getCalendar().get(Calendar.YEAR) <= 9999;
    }

    /**
     * 说明：判断是否为BigDecimal
     *
     * @param integer
     * @return
     */
    public static boolean isBigDecimal(String integer) {
        try {
            new BigDecimal(integer);
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }

}
